#include "UART.h"

#define UART_BASE_ADDRESS 0x100000
#define DATA_OFFSET 0
#define LCR_OFFSET 0x3
#define LSR_OFFSET 0x5
#define DLL_OFFSET 0x0
#define DLH_OFFSET 0x1
#define BAUD_19200_DLL 0x06
#define BAUD_19200_DLH 0
#define DATA_BITS_8 3
#define ONE_STOP_BIT 0


union LCR
{
	unsigned char byte;
	struct 
	{
		unsigned int WordLength : 2;
		unsigned int StopBit : 1;
		unsigned int Parity : 3;
		unsigned int SetBreakEnable : 1;
		unsigned int DLAB : 1;
	} bits;
};

union LSR
{
	unsigned char byte;
	struct 
	{
		unsigned int DataReady : 1;
		unsigned int OverrunError : 1;
		unsigned int ParityError : 1;
		unsigned int FramingError : 1;
		unsigned int BreakInterrupt : 1;
		unsigned int EmptyTransmitterHoldingRegister : 1;		
		unsigned int EmptyDataHoldingRegister : 1;		
		unsigned int ErrorInRecievedFifo : 1;
		
	} bits;
};


unsigned char * UARTBasePointer = (unsigned char *)(UART_BASE_ADDRESS);

void startUpUART()
{
	
	union LCR lcr_byte;
	lcr_byte.bits.WordLength = DATA_BITS_8;
	lcr_byte.bits.Parity = 0;
	lcr_byte.bits.StopBit = ONE_STOP_BIT;
	lcr_byte.bits.DLAB = 1;
	*(UARTBasePointer + LCR_OFFSET) = lcr_byte.byte;
	unsigned char * DLL = (unsigned char*)(UARTBasePointer + DLL_OFFSET);
	*DLL = BAUD_19200_DLL;
	unsigned char * DLH = (unsigned char*)(UARTBasePointer + DLH_OFFSET);	
	*DLH = BAUD_19200_DLH;
}

void UARTsendByte(unsigned char byte)
{
	union LCR lcr_byte;
	lcr_byte.byte = *((unsigned char*)(UARTBasePointer + LCR_OFFSET));
	lcr_byte.bits.DLAB = 0;
	*((unsigned char*)(UARTBasePointer + LCR_OFFSET)) = lcr_byte.byte;
	*((unsigned char *)(UART_BASE_ADDRESS + DATA_OFFSET)) = byte;	
}

unsigned char UARTreceiveByte()
{		
	union LCR lcr_byte;
	lcr_byte.byte = *((unsigned char*)(UARTBasePointer + LCR_OFFSET));
	lcr_byte.bits.DLAB = 0;
	*((unsigned char*)(UARTBasePointer + LCR_OFFSET)) = lcr_byte.byte;
	return *((unsigned char *)(UARTBasePointer + DATA_OFFSET));
}

int UARTreceivedData()
{
	union LSR lsr_byte;
	lsr_byte.byte = *((unsigned char*)(UARTBasePointer + LSR_OFFSET));
	return lsr_byte.bits.DataReady;
}

int UARTreadyToSendData()
{
	union LSR lsr_byte;
	lsr_byte.byte = *((unsigned char*)(UARTBasePointer + LSR_OFFSET));
	return lsr_byte.bits.EmptyDataHoldingRegister;
}

